#include "EstrategiaRecursoUnAlmacenamiento.h"
#include "RecursoAlmacenamiento.h"

namespace Toolkit {

EstrategiaRecursoUnAlmacenamiento::EstrategiaRecursoUnAlmacenamiento(
		const TipoSerializacion tserializacion,	const unsigned long int &tamanoBloque,
		const bool &controlarUnicidad) :
		EstrategiaRecurso(tserializacion, tamanoBloque, controlarUnicidad)
{
}

EstrategiaRecursoUnAlmacenamiento::~EstrategiaRecursoUnAlmacenamiento()
{
}

void EstrategiaRecursoUnAlmacenamiento::guardarDato(const Dato &dato, const Clave &clave)
{
	WrapperComponente wrapper;

	//Chequeo unicidad

	if(getControlUnicidad()) {
		Dato *datoAux = dato.clonar();
		bool encontrado = buscarEnPrimario (clave, *datoAux, wrapper);
		delete datoAux;

		if (encontrado) {
			throw ClaveDuplicadaException();
		}
	}

	unsigned long int posicion = getRecurso()->estrategiaAlmacenamiento->
			guardarDato(*getRecurso()->primario, dato, clave, wrapper);

	if (getRecurso()->indice != NULL) {
		getRecurso()->indice->insertar(clave, posicion);
	}
}

bool EstrategiaRecursoUnAlmacenamiento::recuperarDato(const Clave &clave, Dato &dato)
{
	WrapperComponente wrapper;
	return 	buscarEnPrimario(clave, dato, wrapper);
}

void EstrategiaRecursoUnAlmacenamiento::eliminarDato(const Clave &clave, Dato &dato)
{
	WrapperComponente wrapper;
	unsigned long int posicion;
	if (buscarEnPrimario(clave, dato, wrapper, posicion)) {
		getRecurso()->estrategiaAlmacenamiento->eliminarDato(
				*getRecurso()->primario, posicion, dato, clave, wrapper);

		if (getRecurso()->indice != NULL) {
			getRecurso()->indice->eliminar(clave);
		}
	}
}

void EstrategiaRecursoUnAlmacenamiento::actualizarDato(const Dato &dato, const Clave &clave)
{
	WrapperComponente wrapper;
	unsigned long int posicion;
	Dato *datoAux = dato.clonar();
	try {
        if (buscarEnPrimario(clave, *datoAux, wrapper, posicion)) {
            unsigned long int nuevaPos = getRecurso()->estrategiaAlmacenamiento->modificarDato(
                *getRecurso()->primario, dato, clave, posicion, wrapper);

            if (nuevaPos != posicion && getRecurso()->indice != NULL) {
                getRecurso()->indice->eliminar(clave);
                getRecurso()->indice->insertar(clave, nuevaPos);
            }

        } else {
            posicion = getRecurso()->estrategiaAlmacenamiento->
                guardarDato(*getRecurso()->primario, dato, clave, wrapper);

            if (getRecurso()->indice != NULL) {
                getRecurso()->indice->insertar(clave, posicion);
            }
        }
	} catch (DesbordeDeDatoException &e) {
	    delete datoAux;
	    throw e;
	}

	delete datoAux;

}

}
